package com.nlp.visualization.controller.jersey.controller;

import com.google.gson.Gson;
import com.nlp.visualization.common.CONSTANTS;
import com.nlp.visualization.controller.jersey.error.ErrorCode;
import com.nlp.visualization.core.discourse.DiscourseUtils;
import com.nlp.visualization.pojo.NLP.discourse.WordCloudBackground;
import com.nlp.visualization.pojo.NLP.discourse.WordFrequencyTable;
import com.nlp.visualization.pojo.NLP.discourse.WordsCloudOption;
import com.nlp.visualization.pojo.common.AjaxReturn;
import com.nlp.visualization.service.IDataDiscourseService;
import com.nlp.visualization.utils.ConvertUtils;
import com.nlp.visualization.utils.ImageUtils;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.collections.map.HashedMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.awt.*;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

@Controller
@Path("/discourse")
public class DiscourseController {

    Logger logger = LoggerFactory.getLogger(DiscourseController.class);

    @Autowired
    IDataDiscourseService dataDiscourseService;


    private Gson gson = new Gson();

    private String ContextPath = CONSTANTS.CONTEXT;
    private String CloudSavePath = CONSTANTS.WORDCLOUD_SAVE_PATH;


    /**
     * 生产词云图片
     *
     * @param json
     * @return
     */
    @Path("/wordcloud")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public String wordCloud(String json) {

        Map map;
        Integer width;
        Integer height;
        String bgType;
        String bgColor;
        String font;
        String text;
        String imagePath;
        List<String> texts = new ArrayList<>();
        WordsCloudOption option = new WordsCloudOption();
        Map resultMap = new HashedMap();

        try {

            map = ConvertUtils.jsonToMap(json);
            width = Integer.parseInt(map.get("width") + "");
            height = Integer.parseInt(map.get("height") + "");
            bgColor = (String) map.get("color");
            bgType = (String) map.get("type");
            font = (String) map.get("font");
            text = (String) map.get("text");
            imagePath = (String) map.get("imagePath");

            //判断参数是否为空，并且填充图形
            if (width == null) option.setWidth(930);
            else option.setWidth(width);

            if (height == null) option.setHeight(400);
            else option.setHeight(height);

            if (bgColor == null) option.setBackgroundColor(new Color(0, 0, 0));
            else {
                Color color = ConvertUtils.conver2RGB(bgColor);
                if (color == null) option.setBackgroundColor(new Color(0, 0, 0));
                else option.setBackgroundColor(color);
            }

            if (bgType == null) option.setBgType(WordCloudBackground.CIRCLE);
            else {
                WordCloudBackground type = DiscourseUtils.getWordCloudType(bgType);
                if (type == null) option.setBgType(WordCloudBackground.RECTANGLE);
                else option.setBgType(type);
            }

            if (font == null)
                option.setFont("");
            else option.setFont(font);

            if (text == null)
                texts.add("");
            else texts.add(text);


            //如果已选图片，则按照图片的长宽去生成词云
            File file = DiscourseUtils.getImageName(option.getBgType());
            if (file != null) {
                option.setWidth(ImageUtils.getImgWidth(file));
                option.setHeight(ImageUtils.getImgHeight(file));
                option.setBackgroundImage(file);
            } else {
                try {
                    file = ImageUtils.base64ToFile(imagePath);
                    if (file.isFile()) {
                        option.setBackgroundImage(file);
                        option.setWidth(ImageUtils.getImgWidth(file));
                        option.setHeight(ImageUtils.getImgHeight(file));
                    }

                } catch (Exception e) {
                    logger.error("该图片的路径不存在，故不予执行:" + imagePath);
                }
            }


            //填充保存路径
            option.setSavePath(ContextPath + CloudSavePath);

            //生产词云
            File result = dataDiscourseService.wordClould(texts, option);
//            //删除临时文件
//            if (file != null && option.getBgType()==WordCloudBackground.CUSTOM)
//                file.delete();
            resultMap.put("src", getRePath(result.getPath()));
            resultMap.put("type", bgType);
            resultMap.put("describe", bgType);
            resultMap.put("fileName", result.getName());
            //返回结果
            AjaxReturn res = new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "请求成功", resultMap);
            return gson.toJson(res);
        } catch (Exception e) {
            logger.error("词云生成失败");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "请求失败", null));
        }

    }


    /**
     * 获取词频接口
     *
     * @param json
     * @return
     */
    @Path("/frequency")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public String wordFrequency(String json) {

        Map map = ConvertUtils.jsonToMap(json);
        String text = (String) map.get("text");

        List texts = new ArrayList();
        texts.add(text);
        try {
            List<WordFrequencyTable.sampleWord> sampleWords = dataDiscourseService.wordFrequencyCount(texts).getTable();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", sampleWords));
        } catch (Exception e) {
            logger.error("获取词频异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取词频异常"));
        }
    }


    @POST
    @Path("/namedEntity")
    @Consumes(MediaType.APPLICATION_JSON)
    public String namedEntity(String json) {

        Map map = ConvertUtils.jsonToMap(json);
        String text = (String) map.get("text");
        try {
            List list = dataDiscourseService.wordNamedEntity(text);
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", list));
        } catch (Exception e) {
            logger.error("获取词频异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取命名实体异常"));
        }
    }


    /**
     * 关键词抽取
     *
     * @param json
     * @return
     */
    @Path("/keywords")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    public String getKeywords(String json) {
        String text;
        Integer count;
        try {
            Map map = ConvertUtils.jsonToMap(json);
            text = (String) map.get("text");
            count = ((Integer) map.get("count"));
        } catch (Exception e) {
            logger.error("参数异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "获取摘要传输参数异常"));
        }
        try {
            List list = dataDiscourseService.getKeywords(text, count);
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", list));
        } catch (Exception e) {
            logger.error("获取关键字异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取关键字异常"));
        }

    }


    /**
     * 获取地名集合
     *
     * @param json
     * @return
     */
    @POST
    @Path("/area")
    @Consumes(MediaType.APPLICATION_JSON)
    public String getArea(String json) {
        Map map = ConvertUtils.jsonToMap(json);
        String text = (String) map.get("text");
        try {
            List list = dataDiscourseService.mapRemark(text);
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", list));
        } catch (Exception e) {
            logger.error("获取地名信息异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取地名信息异常"));
        }
    }


    /**
     * 自动摘要接口
     *
     * @param json
     * @return
     */
    @POST
    @Path("/abstract")
    @Consumes(MediaType.APPLICATION_JSON)
    public String autoAbstract(String json) {
        String text;
        Integer count;
        try {
            Map map = ConvertUtils.jsonToMap(json);
            text = (String) map.get("text");
            count = ((Integer) map.get("count"));
        } catch (Exception e) {
            logger.error("参数异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "获取摘要传输参数异常"));
        }
        try {
            List list = dataDiscourseService.getAbstract(text, count);
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", list));
        } catch (Exception e) {
            logger.error("获取摘要异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取摘要异常"));
        }
    }


    /**
     * 获取主题
     *
     * @param json
     * @return
     */
    @POST
    @Path("/theme")
    @Consumes(MediaType.APPLICATION_JSON)
    public String getTheme(String json) {
        Map map = ConvertUtils.jsonToMap(json);
        String text = (String) map.get("text");
        try {
            Map map1 = dataDiscourseService.getTheme(text);
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", map1));
        } catch (Exception e) {
            logger.error("获取主题信息异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取主题异常"));
        }
    }


    /**
     * 获取情感
     *
     * @param json
     * @return
     */
    @POST
    @Path("/emotion")
    @Consumes(MediaType.APPLICATION_JSON)
    public String getEmotion(String json) {
        Map map = ConvertUtils.jsonToMap(json);
        String text = (String) map.get("text");
        try {
            Map map1 = dataDiscourseService.getEmotion(text);
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", map1));
        } catch (Exception e) {
            logger.error("获取情感信息异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取情感异常"));
        }
    }


    /**
     * 获取词向量
     *
     * @param json
     * @return
     */
    @POST
    @Path("/vector")
    @Consumes(MediaType.APPLICATION_JSON)
    public String word2Vec(String json) {
        Map map = ConvertUtils.jsonToMap(json);
        String text = (String) map.get("text");
//        try {
//            Map map1 = dataDiscourseService.getEmotion(text);
//            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", map1));
//        } catch (Exception e) {
//            logger.error("获取地名信息异常");
//            e.printStackTrace();
//            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取情感异常"));
//        }
        return null;
    }


    /**
     * 获取敏感词汇
     *
     * @param json
     * @return
     */
    @POST
    @Path("/sensitive")
    @Consumes(MediaType.APPLICATION_JSON)
    public String getSensitiveWords(String json) {
        String text;
        Integer type;
        try {
            Map map = ConvertUtils.jsonToMap(json);
            text = (String) map.get("text");
            type = ((Integer) map.get("match_type"));
            if (text == null)
                throw new Exception("参数个数不够");
            else if (type == null)
                type = 2;
        } catch (Exception e) {
            logger.error("参数异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "参数异常"));
        }
        try {
            Map map = dataDiscourseService.sensitiveWord(text, type);
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", map));
        } catch (Exception e) {
            logger.error("获取地名信息异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取敏感词异常"));
        }
    }


    /**
     * 计算文本相似度
     *
     * @param json
     * @return
     */
    @POST
    @Path("/similarity")
    @Consumes(MediaType.APPLICATION_JSON)
    public String textNear(String json) {
        String baseText = "";
        String[] compareTexts;
        List texts = new ArrayList();
        try {
            Map map = ConvertUtils.jsonToMap(json);
            baseText = (String) map.get("base");
            JSONArray textArray = (JSONArray) map.get("texts");
            //如果连这个字段都不填，那就直接抛出异常咯
            if (textArray == null)
                throw new Exception();
            Iterator iterator = textArray.iterator();
            while (iterator.hasNext()) {
                JSONObject jsonObject = (JSONObject) iterator.next();
                texts.add(jsonObject.getString("text"));
            }
            compareTexts = new String[texts.size()];
            for (int i = 0; i < texts.size(); i++) {
                compareTexts[i] = (String) texts.get(i);
            }
        } catch (Exception e) {
            logger.error("参数异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "参数异常"));
        }

        try {
            Map res = dataDiscourseService.textNearCalculate(baseText, compareTexts);
            res.put("base", baseText);
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", res));
        } catch (Exception e) {
            logger.error("获取相似度异常");
            e.printStackTrace();
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_UNKNOWN, "获取相似度异常"));
        }
    }


    /**
     * 训练贝叶斯模型
     *
     * @param map
     * @return
     */
    @POST
    @Path("/bayes/training")
    @Consumes(MediaType.APPLICATION_JSON)
    public String trainBayes(String json) {

        Map<String, String[]> dataMap = new HashedMap();
        Map map = ConvertUtils.jsonToMap(json);

        JSONArray textArray = (JSONArray) map.get("data");
        //如果连这个字段都不填，那就直接抛出异常咯
        if (textArray == null)
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "参数异常"));
        //获取需要训练的文本
        Iterator iterator = textArray.iterator();
        while (iterator.hasNext()) {
            List<String> list = new ArrayList<>();
            JSONObject jsonObject = (JSONObject) iterator.next();
            String name = jsonObject.getString("name");
            JSONArray array = jsonObject.getJSONArray("sample");
            Iterator iteratorTemp = array.iterator();
            while (iteratorTemp.hasNext()) {
                JSONObject object = (JSONObject) iteratorTemp.next();
                String sample = object.getString("text");
                list.add(sample);
            }
            String[] strings = new String[list.size()];
            dataMap.put(name, list.toArray(strings));
        }
        //开始训练并且返回一个tag标签
        String tag = dataDiscourseService.traniBayesClassfier(dataMap);
        Map resMap = new HashedMap();
        resMap.put("tag", tag);
        AjaxReturn ajaxReturn = new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", resMap);
        return gson.toJson(ajaxReturn);

    }

    /**
     * 通过tag获取模型
     *
     * @param json
     * @return
     * @throws Exception
     */
    @POST
    @Path("/bayes/classify")
    @Consumes(MediaType.APPLICATION_JSON)
    public String classifyByBayesModel(String json) {


        Map map = ConvertUtils.jsonToMap(json);
        //获取model的tag
        String tag = (String) map.get("tag");
        //获取要测的数据，存放到list中
        JSONArray textArray = (JSONArray) map.get("texts");
        List<String> list = new ArrayList<>();
        //如果连这个字段都不填，那就直接抛出异常咯
        if (textArray == null)
            return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_PARAM_ERROR, "参数异常"));
        //获取需要训练的文本
        Iterator iterator = textArray.iterator();
        while (iterator.hasNext()) {
            JSONObject jsonObject = (JSONObject) iterator.next();
            String text = jsonObject.getString("text");
            list.add(text);
        }
        Map classify = dataDiscourseService.getBayesClassifer(tag, list);

        return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", classify));

    }

    @GET
    @Path("/bayes/models")
    @Consumes(MediaType.APPLICATION_JSON)
    public String getModelTags(String json) {

        return gson.toJson(new AjaxReturn(CONSTANTS.ERROR_SUCCESS, "成功", CONSTANTS.BAYES_MODELS_LIST));

    }


    /**
     * 获得相对于项目的路径。
     *
     * @param path
     * @return
     */
    private String getRePath(String path) {
        try {
            return path.split(ContextPath)[1];
        } catch (Exception e) {
            logger.error("切分路径失败");
            e.printStackTrace();
            return "";
        }
    }

}
